package apiimpl

import (
	"context"
	"go-caipu/pkg/infra/remotecache"
	"go-caipu/pkg/services/admin/sysapi"
	"golang.org/x/sync/singleflight"
	"gorm.io/gorm"
)

// 缓存键设计
const (
	apiCacheKey        = "sys:api:full_list"     // 完整的API列表缓存
	apiCacheLockKey    = "sys:api:cache_lock"    // 缓存重建锁
	apiCacheVersionKey = "sys:api:cache_version" // 缓存版本号
)

type Service struct {
	store        store
	cache        *remotecache.Cache
	singleflight singleflight.Group
}

func ProvideService(db *gorm.DB, cache *remotecache.Cache) (*Service, error) {
	store := ProvideStore(db)
	s := &Service{
		store:        store,
		cache:        cache,
		singleflight: singleflight.Group{},
	}
	return s, nil
}

// GetSysApiPage 获取API列表【管理功能】
func (s *Service) GetSysApiPage(ctx context.Context, cmd sysapi.GetSysApiPageCommand) (result []sysapi.SysApi, num int64, err error) {
	// 尝试从缓存中获取
	result, num, err = s.store.GetSysApiPage(ctx, cmd)
	if err != nil {
		return
	}
	return
}
func (s *Service) GetSysApiList(ctx context.Context) (result []sysapi.SysApi, err error) {
	// 尝试从缓存中获取
	data, ok := s.cache.Get(apiCacheKey)
	if ok {
		return data.([]sysapi.SysApi), nil
	}
	// 使用singleflight防止缓存击穿(业务量不多，其实也不用）
	data, err, shared := s.singleflight.Do(apiCacheKey, func() (interface{}, error) {
		//fmt.Printf("Executing database query for key: %s\n", apiCacheKey)
		cmd := sysapi.GetSysApiPageCommand{}
		cmd.PageSize = 1000
		result, _, err = s.GetSysApiPage(ctx, cmd)
		if err != nil {
			return nil, err
		}
		// 设置缓存，TTL根据业务需求调整
		s.cache.Set(apiCacheKey, result, 0)
		return result, nil
	})

	if shared {
		//fmt.Printf("Result for key %s was shared among multiple callers\n", apiCacheKey)
	}
	if err != nil {
		return
	}
	return data.([]sysapi.SysApi), err
}

func (s *Service) Get(ctx context.Context, cmd sysapi.GetSysApiCommand) (sysapi.SysApi, error) {
	return s.store.Get(ctx, cmd)
}

func (s *Service) Insert(ctx context.Context, cmd sysapi.SysApi) error {
	err := s.store.Insert(ctx, cmd)
	if err == nil {
		s.cache.Delete([]string{apiCacheKey}, "")
	}
	return err
}

// BatchInsert 批量插入
func (s *Service) BatchInsert(ctx context.Context, cmd []sysapi.ApiCategory) (err error) {
	err = s.store.BatchInsert(ctx, cmd)
	if err == nil {
		s.cache.Delete([]string{apiCacheKey}, "")
	}
	return nil
}
func (s *Service) Update(ctx context.Context, cmd sysapi.SysApi) error {
	s.cache.Delete([]string{apiCacheKey}, "")
	return s.store.Update(ctx, cmd)
}

func (s *Service) Remove(ctx context.Context, cmd sysapi.RemoveSysApiCommand) error {
	s.cache.Delete([]string{apiCacheKey}, "")
	return s.store.Remove(ctx, cmd)
}

func (s *Service) GetSysApiCategoryTree(ctx context.Context, cmd sysapi.GetApiCategoriesCommand) (result []*sysapi.ApiCategory, err error) {
	var categories []sysapi.ApiCategory
	categories, err = s.store.GetSysApiCategoryList(ctx, cmd)

	if err != nil {
		return
	}
	//构建分类映射
	categoryMap := make(map[int64]*sysapi.ApiCategory)
	for _, category := range categories {
		categoryMap[category.ID] = &category
	}
	//构建树形结构
	// 构建树形结构
	var rootCategories []*sysapi.ApiCategory
	for _, category := range categories {
		if category.ParentID == 0 {
			rootCategories = append(rootCategories, categoryMap[category.ID])
		} else {
			parent, ok := categoryMap[category.ParentID]
			if ok {
				if parent.Children == nil {
					parent.Children = make([]*sysapi.ApiCategory, 0)
				}
				parent.Children = append(parent.Children, categoryMap[category.ID])
			}
		}
	}
	//将api接口关联到分类中（菜单设置接口时使用）
	if cmd.IsApi {
		var apis []sysapi.SysApi
		apis, err = s.store.GetSysApi(ctx, nil)
		if err != nil {
			return rootCategories, err
		}

		for _, api := range apis {
			category, ok := categoryMap[api.Category]
			if ok {
				category.Children = append(category.Children, &sysapi.ApiCategory{ID: api.Id, Type: 1, Title: api.Title})
			}
		}
	}
	return rootCategories, nil
}

//ExportSysApiCategory 导出分类接口信息（导出接口给插件使用带完整的接口信息）
/**
 * @Author: go-caipu
 * @Date: 2024/6/24 16:26
 * @Description: 导出分类接口信息（导出接口给插件使用带完整的接口信息）
 * @param ctx 对象上下文
 * @param cmd 请求参数
 * @return result 分类信息
 * @return err 错误信息
 */
func (s *Service) ExportSysApiCategory(ctx context.Context, cmd sysapi.GetApiCategoriesCommand) (result []sysapi.ApiCategory, err error) {
	var categories []sysapi.ApiCategory
	categories, err = s.store.GetSysApiCategoryList(ctx, cmd)
	if err != nil {
		return
	}
	var apis []sysapi.SysApi
	apis, err = s.store.GetSysApi(ctx, cmd.Ids)
	for i, category := range categories {
		for _, v := range apis {
			if category.ID == v.Category {
				if categories[i].SysApis == nil {
					categories[i].SysApis = make([]*sysapi.SysApi, 0)
				}
				categories[i].SysApis = append(categories[i].SysApis, &v)
			}
		}
	}
	return categories, nil
}

func (s *Service) InsertApiCategory(ctx context.Context, cmd sysapi.ApiCategory) error {
	return s.store.InsertApiCategory(ctx, cmd)
}
func (s *Service) UpdateApiCategory(ctx context.Context, cmd sysapi.ApiCategory) error {
	return s.store.UpdateApiCategory(ctx, cmd)
}
func (s *Service) RemoveApiCategory(ctx context.Context, cmd sysapi.ApiCategory) error {
	return s.store.RemoveApiCategory(ctx, cmd)
}
